package tako.wisers.com.android.apis.location;

import tako.wisers.com.android.apis.R;
import tako.wisers.com.android.apis.util.Configration;
import tako.wisers.com.android.apis.util.Global;
import tako.wisers.com.android.apis.util.LocationRange;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.MapView.ReticleDrawMode;

import android.app.Activity;
import android.content.Context;
import android.location.Address;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.widget.Toast;

public class GPSManager implements LocationListener {

	private Activity mactivity;
	private MapView mMapView;
	private MapController mc;
	public LocationDecord mld;
	private static GPSManager mgpsL;
	private OverlayControl mOverlayControl;
	private boolean isListener;
	private LocationManager mlm;

	public static final String LATITUDE_DEFAULT_KEY = "GPS.default.latitude";
	public static final String LONGITUDE_DEFAULT_KEY = "GPS.default.longitude";

	private GPSManager(Activity activity, MapView mMapView) {
		mactivity = activity;
		this.mMapView = mMapView;
		mOverlayControl = new OverlayControl(mMapView);
		mOverlayControl.build(activity);
		init();
	}

	public static void build(Activity activity, MapView mMapView) {
		mgpsL = new GPSManager(activity, mMapView);
		Configration conf = Configration.getInstance();
		double lat = conf.getDouble(LATITUDE_DEFAULT_KEY);
		double lon = conf.getDouble(LONGITUDE_DEFAULT_KEY);
		mgpsL.setLocation(lat, lon);
	}

	public static GPSManager getInstance() {
		return mgpsL;
	}

	private void init() {
		mc = mMapView.getController();
		mMapView.setBuiltInZoomControls(true);
		mMapView.setReticleDrawMode(ReticleDrawMode.DRAW_RETICLE_OVER);
		if(mld == null){
			mld = new LocationDecord(mactivity.getApplicationContext());
		}
		initLocation();
	}

	public void onLocationChanged(Location loc) {
		if (loc != null && isListener) {
			setLocation(loc.getLatitude(), loc.getLongitude());
		}
	}

	public GeoPoint getGPSCenter() {
		int lat = Math.round((float) mld.getLat() * Global.MILLION);
		int lon = Math.round((float) mld.getLon() * Global.MILLION);
		return new GeoPoint(lat, lon);
	}

	public void setGPSListener(boolean listenerUp) {
		this.isListener = listenerUp;
	}

	public boolean isListener() {
		return isListener;
	}

	public void setLocation(double lat, double lon) {
		GeoPoint point = new GeoPoint((int) (lat * 1E6), (int) (lon * 1E6));
		mMapView.getController().animateTo(point);
		mc.setZoom(mMapView.getZoomLevel());
		mld.executePoint(lat, lon);
		mhandler.sendMessage(mhandler.obtainMessage());
	}

	private android.os.Handler mhandler = new android.os.Handler() {
		@Override
		public void handleMessage(android.os.Message msg) {
			mMapView.invalidate();
		}
	};

	public void setLocation(GeoPoint point) {
		double lat = (double) point.getLatitudeE6() / Global.MILLION;
		double lon = (double) point.getLongitudeE6() / Global.MILLION;
		setLocation(lat, lon);
	}

	public void setLocationByName(String name) {
		Address address = mld.getLocationByName(name);
		if (address != null) {
			setLocation(address.getLatitude(), address.getLongitude());
		} else {
			String msg = mactivity.getText(R.string.search_failed).toString();
			Toast.makeText(mactivity, String.format(msg, name),
					Toast.LENGTH_SHORT);
		}
	}

	public static boolean isBuilded() {
		return mgpsL != null;
	}

	public String getLocationName() {
		return mld.getLocationName();
	}

	public String getCountryCode() {
		return mld.getCountryCode();
	}

	public void onProviderDisabled(String provider) {
		// TODO Auto-generated method stub
	}

	public void onProviderEnabled(String provider) {
		// TODO Auto-generated method stub
	}

	public MapView getMapView() {
		return mMapView;
	}

	public void onStatusChanged(String provider, int status, Bundle extras) {
		// TODO Auto-generated method stub
	}

	public OverlayControl getOverlayControl() {
		return mOverlayControl;
	}

	public synchronized static LocationRange getLocationRange(GeoPoint center) {
		if (center == null)
			return null;
		int latitudeE6 = center.getLatitudeE6();
		int longitudeE6 = center.getLongitudeE6();

		int latHalfSpan = mgpsL.mMapView.getLatitudeSpan() >> 1;
		int longHalfSpan = mgpsL.mMapView.getLongitudeSpan() >> 1;

		float minLong = ((float) (longitudeE6 - longHalfSpan)) / Global.MILLION;
		float maxLong = ((float) (longitudeE6 + longHalfSpan)) / Global.MILLION;

		float minLat = ((float) (latitudeE6 - latHalfSpan)) / Global.MILLION;
		float maxLat = ((float) (latitudeE6 + latHalfSpan)) / Global.MILLION;

		return new LocationRange(minLong, maxLong, minLat, maxLat);
	}

	public void initLocation() {
		mlm = (LocationManager) mactivity
				.getSystemService(Context.LOCATION_SERVICE);
		mlm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 3000, 0, this);
	}
	
	public boolean isStartUp(){
		return mlm != null;
	}
}
